package com.ma.config;

import com.ma.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Security核心配置
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
//开启基于方法的安全认证机制，也就是说在web层的controller启用注解机制的安全确认
//只有加了@EnableGlobalMethodSecurity(prePostEnabled=true) 那么在上面使用的 @PreAuthorize(“hasAuthority(‘admin’)”)才会生效
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    LoginSuccessHandler loginSuccessHandler;
    @Autowired
    LoginFailureHandler loginFailureHandler;
    @Autowired
    CaptchaFilter captchaFilter;
    @Autowired
    JwtAccessDeniedHandler jwtAccessDeniedHandler;
    @Autowired
    JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    @Autowired
    UserDetalisServiceImpl userDetalisService;
    @Autowired
    JwtLogoutSucessHandler jwtLogoutSucessHandler;

    //因为重写了构造方法 需要重新注入容器
    @Bean
    JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
        JwtAuthenticationFilter jwtAuthenticationFilter=new JwtAuthenticationFilter(authenticationManager());
        return jwtAuthenticationFilter;
    }
    //配置加密形式
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //定义白名单
    private static String[] URL_WHITELIST= {
            "/login",
            "/logout",
            "/captcha",
            "/favicon.ico"
    };

    //配置http相关安全的
    protected void configure(HttpSecurity http) throws Exception {

        //允许跨越
        http.cors().and()
        //关闭预防攻击 //关闭打开的csrf保护
        .csrf().disable()

        //登录配置
        .formLogin()
                //配置认证成功处理器
                .successHandler(loginSuccessHandler)
                //配置认证失败处理器
                .failureHandler(loginFailureHandler)
        //登录退出配置
        .and()
        .logout()
        .logoutSuccessHandler(jwtLogoutSucessHandler)

           /*
            always：保存session状态
            never：不会创建HttpSession，但是会使用已经存在的HttpSession
            if_required：仅在需要HttpSession创建
            stateless：不会保存session状态
            */
        //禁用session
                .and()
                .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

        //配置拦截规则
        .and()
        .authorizeRequests()
        .antMatchers(URL_WHITELIST).permitAll() //白名单
        .anyRequest().authenticated() //其他访问路径都需要登录操作

        //配置异常处理器
        .and()
        .exceptionHandling()
        .authenticationEntryPoint(jwtAuthenticationEntryPoint)  //认证入口点 用户请求处理过程中遇到认证异常
        .accessDeniedHandler(jwtAccessDeniedHandler)       //权限不足处理器

        //配置自定义过滤器
        // 在用户名登录之前设置验证码过滤器
        .and()
        .addFilter(jwtAuthenticationFilter())
        .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)

;
   }
   //配置service


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(userDetalisService);
    }
}
